﻿using System;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace Actor.Net.Network.Actor.Adapter
{
    /// <summary>
    /// 消息适配器基类
    /// </summary>
    /// <typeparam name="TRequestMessage"></typeparam>
    /// <typeparam name="TResponseResult"></typeparam>
    public abstract class ActorAdapter<TRequestMessage, TResponseResult> : ActorAdapter<TRequestMessage>
        where TRequestMessage : class, new()
    {
        /// <summary>
        /// 网络IO接口
        /// </summary>
        /// <param name="context"></param>
        /// <param name="requestMessage"></param>
        public override void OnRequest(ActorTransferContext context, TRequestMessage requestMessage)
        {
            try
            {
                var output = this.OnRequestMessage(context.ChannelContext, requestMessage);
                context.Output(output);
            }
            catch(Exception ex)
            {
                context.ChannelContext.Channel.NetService.ProcessSocketError(context.ChannelContext, ex);
            }
        }

        /// <summary>
        /// 同步消息处理接口
        /// </summary>
        /// <param name="context"></param>
        /// <param name="requestMessage"></param>
        /// <returns></returns>
        public virtual TResponseResult OnRequestMessage(ActorChannelContext context, TRequestMessage requestMessage)
        {
            return default;
        }
    }

    /// <summary>
    /// 消息适配器基类
    /// </summary>
    /// <typeparam name="TRequestMessage"></typeparam>
    public abstract class ActorAdapter<TRequestMessage> : IActorAdapter<TRequestMessage>
        where TRequestMessage : new()
    {
        /// <summary>
        /// 网络IO接口
        /// </summary>
        /// <param name="context"></param>
        /// <param name="requestMessage"></param>
        public abstract void OnRequest(ActorTransferContext context, TRequestMessage requestMessage);

        /// <summary>
        /// 消息分发
        /// </summary>
        /// <param name="context"></param>
        public void DispatchAdapter(ActorTransferContext context)
        {
            try
            {
                TRequestMessage requestMessage = default;
                var type = typeof(TRequestMessage);
                if (type == typeof(byte[]))
                {
                    var len = (int)context.BodyStream.Length;
                    object bytes = new byte[len];
                    context.BodyStream.Read(bytes as byte[], 0, len);
                    requestMessage = (TRequestMessage)bytes;
                }
                else if (type == typeof(string))
                {
                    var len = (int)context.BodyStream.Length;
                    var bytes = new byte[context.BodyStream.Length];
                    context.BodyStream.Read(bytes, 0, bytes.Length);
                    object str = Encoding.UTF8.GetString(bytes);
                    requestMessage = (TRequestMessage)str;
                }
                else
                {
                    requestMessage = MessagePack.MessagePackSerializer.Deserialize<TRequestMessage>(context.BodyStream);
                }

                this.OnRequest(context, requestMessage);
            }
            catch (Exception ex)
            {
                context.ChannelContext.Channel.NetService.ProcessSocketError(context.ChannelContext, ex);
            }
        }
    }
}